/*
 * @brief Sensor Hub demo GL callback (implementation file)
 *
 * @note
 * Copyright(C) NXP Semiconductors, 2015
 * All rights reserved.
 *
 * @par
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * LPC products.  This software is supplied "AS IS" without any warranties of
 * any kind, and NXP Semiconductors and its licensor disclaim any and
 * all warranties, express or implied, including all implied warranties of
 * merchantability, fitness for a particular purpose and non-infringement of
 * intellectual property rights.  NXP Semiconductors assumes no responsibility
 * or liability for the use of the software, conveys no license or rights under any
 * patent, copyright, mask work right, or any other intellectual property rights in
 * or to any products. NXP Semiconductors reserves the right to make changes
 * in the software without notification. NXP Semiconductors also makes no
 * representation or warranty that such application will be suitable for the
 * specified use without further testing or modification.
 *
 * @par
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, under NXP Semiconductors' and its
 * licensor's relevant copyrights in the software, without fee, provided that it
 * is used in conjunction with NXP Semiconductors microcontrollers.  This
 * copyright, permission, and disclaimer notice must appear in all copies of
 * this code.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include "trace.h"
#include "gl_menu.h"
#include "gl_text.h"
#include "auto_rotate.h"
#include "sensors.h"
#include "teapot.h"

#include "sensor_demo.h"

#include "gl_callback.h"

/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/
static char			text_buffer[128];											/* Text buffer size */
static const int	refresh = 1000/REFRESH_RATE;								/* Refresh rate in ms (between 10 and 100) */

/*****************************************************************************
 * Private functions
 ****************************************************************************/

static void info_display(void)
{
	TEXT_INFO_T	t_info;
	uint32_t	hud_item = gl_menu_disp_get();

	gl_text_info_init(&t_info);
	gl_text_begin();

	sprintf(text_buffer, "Sensor Demo HUD                                  Right click for menu");
	gl_text_print(&t_info, text_buffer);

	sprintf(text_buffer, "USB Connection: %s", (auto_rotate_get() == true) ? "disconnected" : "connected");
	gl_text_print(&t_info, text_buffer);

	if (auto_rotate_get() == true) {
		sprintf(text_buffer, "         Angle: %.2f", angle_get());
		gl_text_print(&t_info, text_buffer);
	} else {
		disp_timestamp(&t_info);																		// display the time-stamp
		gl_text_blank(&t_info);																			// skip a line
		if (hud_item & DISP_ACCELEROMETER)					accel_cal_update_hud(&t_info);				// calibrated accelerometer data
		if (hud_item & DISP_ACCELEROMETER_UNCALIBRATED)		accel_uncal_update_hud(&t_info);			// uncalibrated accelerometer data
		if (hud_item & DISP_MAGNETIC_FIELD)					mag_cal_update_hud(&t_info);				// calibrated magnetometer data
		if (hud_item & DISP_MAGNETIC_FIELD_UNCALIBRATED)	mag_uncal_update_hud(&t_info);				// uncalibrated magnetometer data
		if (hud_item & DISP_GYROSCOPE)						gyro_cal_update_hud(&t_info);				// calibrated gyroscope data
		if (hud_item & DISP_GYROSCOPE_UNCALIBRATED)			gyro_uncal_update_hud(&t_info);				// uncalibrated gyroscope data
		if (hud_item & DISP_LIGHT)							light_update_hud(&t_info);					// light data
		if (hud_item & DISP_PRESSURE)						pressure_update_hud(&t_info);				// barometer pressure data
		if (hud_item & DISP_PROXIMITY)						proximity_update_hud(&t_info);				// proximity data
		if (hud_item & DISP_ROTATION_VECTOR)				rotation_update_hud(&t_info);				// accel+mag+gyro quaternion (vector only)
	}
	gl_text_end();
}

/*****************************************************************************
 * Public functions
 ****************************************************************************/


/**
 * @brief
 * @return	Nothing
 */
void draw_callback(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);							/* clear the color and depth buffers */
	glPushMatrix();																/* preserve modelview matrix */

	if (auto_rotate_get() == true) {											/* rotate by angle degrees around the axis y = x */
		glRotatef(angle_get(), 1.0f, 1.0f, 0.0f);
	} else {
		teapot_update_gl();
	}
	glutSolidTeapot(2.0f);														/* render a solid teapot */

	if (gl_menu_hud_get() == true) info_display();								/* Information Display */

	glPopMatrix();																/* return to previous modelview matrix */
	glutSwapBuffers();															/* swap front and back buffers */
}

/**
 * @brief
 * @return	Nothing
 */
void resize_callback(int width, int height)
{
	gl_text_update(width, height);												/* register new size with text module */
	glViewport(0, 0, width, height);											/* set the viewport to the window width and height */
	glMatrixMode(GL_PROJECTION);												/* load a projection matrix that matches the window aspect ratio */
	glLoadIdentity();
	gluPerspective(45.0, (double)width / (double)height, 1.0, 100.0);
	glMatrixMode(GL_MODELVIEW);													/* return to modelview matrix mode*/
}

/**
 * @brief
 * @return	Nothing
 */
void timer_callback(int value)
{
	angle_bump();																/* keep angle between 0 and 360 */
	glutPostRedisplay();														/* send redisplay event */
	glutTimerFunc(refresh, timer_callback, 0);									/* reset the timer */
}

int refresh_get(void)
{
	return refresh;
}